﻿using System;
using System.Windows.Threading;
using DocumentListModule.Services;
using Infrastructure.Events;
using Infrastructure.ViewModels;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Unity;

namespace DocumentListModule.Views
{
    /// <summary>
    /// Document list presenter class
    /// </summary>
    public class DocumentListPresenter : IDocumentListPresenter
    {
        readonly IEventAggregator _eventAggregator;
        AllCatalogItemsViewModel _allCatalogItemsViewModel;
        IUnityContainer _container;

        /// <summary>
        /// Gets or sets the view.
        /// </summary>
        /// <value>The view.</value>
        public IDocumentListView View { get; set;}

        /// <summary>
        /// Initializes a new instance of the <see cref="DocumentListPresenter"/> class.
        /// </summary>
        public DocumentListPresenter()
        {
            
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DocumentListPresenter"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <param name="eventAggregator">The event aggregator.</param>
        /// <param name="view">The view.</param>
        public DocumentListPresenter(IUnityContainer container, IEventAggregator eventAggregator, IDocumentListView view)
            : this()
        {
            _container = container;
            _eventAggregator = eventAggregator;
            View = view;

            BookshelfChangedEvenet bookshelfChangedEvenet = _eventAggregator.GetEvent<BookshelfChangedEvenet>();
            bookshelfChangedEvenet.Subscribe(BookshelfChangedEventHandler, true);

            DocumentDeletedEvent documentDeletedEvent = _eventAggregator.GetEvent<DocumentDeletedEvent>();
            documentDeletedEvent.Subscribe(DocumentDeletedEventHandler, true);

            DocumentSavedEvent documentSavedEvent = _eventAggregator.GetEvent<DocumentSavedEvent>();
            documentSavedEvent.Subscribe(DocumentSavedEventHandler, true);

            DocumentUpdatedEvent documentUpdatedEvent = _eventAggregator.GetEvent<DocumentUpdatedEvent>();
            documentUpdatedEvent.Subscribe(DocumentUpdatedEventHandler, true);
        }

        /// <summary>
        /// Document updated event handler.
        /// </summary>
        /// <param name="item">The updated document.</param>
        void DocumentUpdatedEventHandler(CatalogItemViewModel item)
        {
            // Update document in the list
            for (int i = 0; i < _allCatalogItemsViewModel.CatalogItems.Count; i++)
            {
                if(_allCatalogItemsViewModel.CatalogItems[i].Id == item.Id)
                {
                    _allCatalogItemsViewModel.CatalogItems[i] = item;
                    break;
                }
            }
        }

        /// <summary>
        /// Document saved event handler.
        /// </summary>
        /// <param name="item">The item.</param>
        void DocumentSavedEventHandler(CatalogItemViewModel item)
        {
            _allCatalogItemsViewModel.CatalogItems.Add(item);
        }

        /// <summary>
        /// Document deleted event handler.
        /// </summary>
        /// <param name="item">The item.</param>
        void DocumentDeletedEventHandler(CatalogItemViewModel item)
        {
            _allCatalogItemsViewModel.CatalogItems.Remove(item);
        }

        /// <summary>
        /// Bookshelf changed event handler.
        /// </summary>
        /// <param name="bookshelf">The bookshelf.</param>
        void BookshelfChangedEventHandler(Bookshelf bookshelf)
        {
            if (bookshelf == null)
            {
                ClearDocumentList();
            }
            else
            {
                // HACK Couldn't figure out other solution for the problem without DataModel Dispatcher modification
                View.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                            (Action) delegate
                                                         {
                                                             _allCatalogItemsViewModel = new AllCatalogItemsViewModel();
                                                             _allCatalogItemsViewModel.Loaded +=
                                                                 AllCatalogItemsViewModelOnLoaded;
                                                         });
            }
        }

        /// <summary>
        /// Clears the document list.
        /// </summary>
        void ClearDocumentList()
        {
            View.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                (Action)delegate
                                                    {
                                                        View.Model = null;
                                                    });
        }

        /// <summary>
        /// Document loading finished in the view model
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void AllCatalogItemsViewModelOnLoaded(object sender, EventArgs args)
        {
            AssignCatalogItems();
        }

        /// <summary>
        /// Assigns the catalog items.
        /// </summary>
        void AssignCatalogItems()
        {
            View.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
                                        (Action)delegate
                                                    {
                                                        View.Model = _allCatalogItemsViewModel.CatalogItems;
                                                    });
        }
    }
}